5 追隨者

資料快取

資料快取是將一些 PHP 變數儲存在快取中,並在稍後從快取中檢索出來。它也是更進階快取功能的基礎,例如 查詢快取頁面快取

以下程式碼是資料快取的典型用法模式,其中 $cache 指的是 快取組件

// try retrieving $data from cache
$data = $cache->get($key);

if ($data === false) {
    // $data is not found in cache, calculate it from scratch
    $data = $this->calculateSomething();

    // store $data in cache so that it can be retrieved next time
    $cache->set($key, $data);
}

// $data is available here

自 2.0.11 版本起,快取組件 提供了 getOrSet() 方法,簡化了資料取得、計算和儲存的程式碼。以下程式碼與先前的範例執行完全相同的操作

$data = $cache->getOrSet($key, function () {
    return $this->calculateSomething();
});

當快取具有與 $key 相關聯的資料時,將傳回快取的值。否則,將執行傳遞的匿名函式以計算將被快取並傳回的值。

如果匿名函式需要來自外部作用域的一些資料,您可以使用 use 語句傳遞它。例如

$user_id = 42;
$data = $cache->getOrSet($key, function () use ($user_id) {
    return $this->calculateSomething($user_id);
});

注意: getOrSet() 方法也支援持續時間和依賴性。請參閱 快取過期快取依賴 以了解更多資訊。

快取組件

資料快取依賴於所謂的快取組件,這些組件代表各種快取儲存,例如記憶體、檔案、資料庫。

快取組件通常註冊為 應用程式組件,以便它們可以全局配置和存取。以下程式碼顯示如何配置 cache 應用程式組件以使用 memcached 與兩個快取伺服器

'components' => [
    'cache' => [
        'class' => 'yii\caching\MemCache',
        'servers' => [
            [
                'host' => 'server1',
                'port' => 11211,
                'weight' => 100,
            ],
            [
                'host' => 'server2',
                'port' => 11211,
                'weight' => 50,
            ],
        ],
    ],
],

然後,您可以使用表達式 Yii::$app->cache 存取上述快取組件。

如果未指定快取組件,則 Yii 將使用 yii\caching\FileCache 作為預設值。

由於所有快取組件都支援相同的 API 集,您可以通過在應用程式配置中重新配置它,來將底層快取組件與不同的組件交換,而無需修改使用快取的程式碼。例如,您可以修改上述配置以使用 APC 快取

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
    ],
],

提示: 您可以註冊多個快取應用程式組件。名為 cache 的組件預設由許多依賴快取的類別(例如 yii\web\UrlManager)使用。

支援的快取儲存

Yii 支援廣泛的快取儲存。以下是摘要

  • yii\caching\ApcCache:使用 PHP APC 擴展。當處理集中式厚應用程式的快取時(例如,一台伺服器,沒有專用的負載平衡器等),此選項可以被認為是最快的選項。
  • yii\caching\DbCache:使用資料庫表來儲存快取資料。要使用此快取,您必須建立一個表,如 yii\caching\DbCache::$cacheTable 中所指定。
  • yii\caching\ArrayCache:僅為當前請求提供快取,方法是將值儲存在陣列中。為了提高 ArrayCache 的效能,您可以通過將 yii\caching\ArrayCache::$serializer 設定為 false 來停用儲存資料的序列化。
  • yii\caching\DummyCache:充當快取佔位符,不執行真正的快取。此組件的目的是簡化需要檢查快取可用性的程式碼。例如,在開發期間或如果伺服器沒有實際的快取支援,您可以配置快取組件以使用此快取。當啟用實際的快取支援時,您可以切換為使用相應的快取組件。在這兩種情況下,您都可以使用相同的程式碼 Yii::$app->cache->get($key) 來嘗試從快取中檢索資料,而無需擔心 Yii::$app->cache 可能為 null
  • yii\caching\FileCache:使用標準檔案來儲存快取資料。這特別適合快取大量資料,例如頁面內容。
  • yii\caching\MemCache:使用 PHP memcachememcached 擴展。當在分散式應用程式中處理快取時(例如,有多個伺服器、負載平衡器等),此選項可以被認為是最快的選項。
  • yii\redis\Cache:基於 Redis 鍵值儲存(需要 redis 版本 2.6.12 或更高版本)實作快取組件。
  • yii\caching\WinCache:使用 PHP WinCache (另請參閱) 擴展。
  • yii\caching\XCache (已棄用):使用 PHP XCache 擴展。
  • yii\caching\ZendDataCache (已棄用):使用 Zend Data Cache 作為底層快取媒介。

提示: 您可以在同一個應用程式中使用不同的快取儲存。常見的策略是使用基於記憶體的快取儲存來儲存小但經常使用的資料(例如,統計資料),並使用基於檔案或資料庫的快取儲存來儲存大且不經常使用的資料(例如,頁面內容)。

快取 API

所有快取組件都具有相同的基類 yii\caching\Cache,因此支援以下 API

  • get():從快取中檢索具有指定鍵的資料項目。如果資料項目在快取中找不到或已過期/失效,將傳回 false 值。
  • set():將由鍵標識的資料項目儲存在快取中。
  • add():如果鍵在快取中找不到,則將由鍵標識的資料項目儲存在快取中。
  • getOrSet():從快取中檢索具有指定鍵的資料項目,或執行傳遞的回調,將回調的傳回值儲存在快取中,並傳回該資料。
  • multiGet():從快取中檢索具有指定鍵的多個資料項目。
  • multiSet():將多個資料項目儲存在快取中。每個項目都由一個鍵標識。
  • multiAdd():將多個資料項目儲存在快取中。每個項目都由一個鍵標識。如果鍵已存在於快取中,則將跳過資料項目。
  • exists():傳回一個值,指示在快取中是否找到指定的鍵。
  • delete():從快取中移除由鍵標識的資料項目。
  • flush():從快取中移除所有資料項目。

注意: 不要直接快取 false 布林值,因為 get() 方法使用 false 傳回值來指示在快取中找不到資料項目。您可以將 false 放在陣列中,並快取此陣列以避免此問題。

某些快取儲存(例如 MemCache、APC)支援以批次模式檢索多個快取值,這可以減少檢索快取資料所涉及的開銷。提供了 API multiGet()multiAdd() 以利用此功能。如果底層快取儲存不支援此功能,則將模擬它。

由於 yii\caching\Cache 實作了 ArrayAccess,因此快取組件可以像陣列一樣使用。以下是一些範例

$cache['var1'] = $value1;  // equivalent to: $cache->set('var1', $value1);
$value2 = $cache['var2'];  // equivalent to: $value2 = $cache->get('var2');

快取鍵

儲存在快取中的每個資料項目都由一個鍵唯一標識。當您在快取中儲存資料項目時,您必須為其指定一個鍵。稍後,當您從快取中檢索資料項目時,您應該提供相應的鍵。

您可以使用字串或任意值作為快取鍵。當鍵不是字串時,它將自動序列化為字串。

定義快取鍵的常見策略是將所有決定因素包含在陣列中。例如,yii\db\Schema 使用以下鍵來快取關於資料庫表的結構描述資訊

[
    __CLASS__,              // schema class name
    $this->db->dsn,         // DB connection data source name
    $this->db->username,    // DB connection login user
    $name,                  // table name
];

如您所見,該鍵包含唯一指定資料庫表所需的所有必要資訊。

注意: 通過 multiSet()multiAdd() 儲存在快取中的值只能具有字串或整數鍵。如果您需要設定更複雜的鍵,請通過 set()add() 單獨儲存該值。

當不同的應用程式使用相同的快取儲存時,您應該為每個應用程式指定唯一的快取鍵前綴,以避免快取鍵衝突。這可以通過配置 yii\caching\Cache::$keyPrefix 屬性來完成。例如,在應用程式配置中,您可以編寫以下程式碼

'components' => [
    'cache' => [
        'class' => 'yii\caching\ApcCache',
        'keyPrefix' => 'myapp',       // a unique cache key prefix
    ],
],

為了確保互操作性,應僅使用字母數字字元。

快取過期

儲存在快取中的資料項目將永遠保留在那裡,除非由於某些快取策略強制執行(例如,快取空間已滿且最舊的資料被移除)而被移除。要更改此行為,您可以在調用 set() 以儲存資料項目時提供過期參數。該參數指示資料項目可以在快取中保持有效的秒數。當您調用 get() 來檢索資料項目時,如果它已超過過期時間,則該方法將傳回 false,指示在快取中找不到資料項目。例如,

// keep the data in cache for at most 45 seconds
$cache->set($key, $data, 45);

sleep(50);

$data = $cache->get($key);
if ($data === false) {
    // $data is expired or is not found in the cache
}

自 2.0.11 版本起,如果您希望自訂快取持續時間而不是預設的無限持續時間,您可以在快取組件配置中設定 defaultDuration 值。這將允許您不必每次都將自訂 duration 參數傳遞給 set()

快取依賴

除了過期設定外,快取資料項目也可能因所謂的快取依賴的更改而失效。例如,yii\caching\FileDependency 表示檔案修改時間的依賴性。當此依賴性更改時,表示相應的檔案已修改。因此,應使在快取中找到的任何過時的檔案內容失效,並且 get() 調用應傳回 false

快取依賴表示為 yii\caching\Dependency 後代類別的物件。當您調用 set() 以在快取中儲存資料項目時,您可以傳遞關聯的快取依賴物件。例如,

// Create a dependency on the modification time of file example.txt.
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);

// The data will expire in 30 seconds.
// It may also be invalidated earlier if example.txt is modified.
$cache->set($key, $data, 30, $dependency);

// The cache will check if the data has expired.
// It will also check if the associated dependency was changed.
// It will return false if any of these conditions are met.
$data = $cache->get($key);

以下是可用快取依賴的摘要

注意: 避免將 exists() 方法與依賴項一起使用。它不檢查與快取資料關聯的依賴項(如果有的話)是否已更改。因此,調用 get() 可能會傳回 false,而 exists() 傳回 true

查詢快取

查詢快取是建立在資料快取之上的特殊快取功能。它旨在快取資料庫查詢的結果。

查詢快取需要 資料庫連線 和有效的 cache 應用程式組件。查詢快取的基本用法如下,假設 $dbyii\db\Connection 實例

$result = $db->cache(function ($db) {

    // the result of the SQL query will be served from the cache
    // if query caching is enabled and the query result is found in the cache
    return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();

});

查詢快取可用於 DAO 以及 ActiveRecord

$result = Customer::getDb()->cache(function ($db) {
    return Customer::find()->where(['id' => 1])->one();
});

資訊: 某些 DBMS(例如 MySQL)也支援 DB 伺服器端的查詢快取。您可以選擇使用任一查詢快取機制。上面描述的查詢快取的優勢在於,您可以指定彈性的快取依賴性,並且可能更有效率。

自 2.0.14 版本起,您可以使用以下快捷方式

(new Query())->cache(7200)->all();
// and
User::find()->cache(7200)->all();

配置

查詢快取通過 yii\db\Connection 具有三個全局可配置選項

  • enableQueryCache:是否開啟或關閉查詢快取。預設為 true。請注意,要有效地開啟查詢快取,您還需要具有有效的快取,如 queryCache 所指定。
  • queryCacheDuration:這表示查詢結果可以在快取中保持有效的秒數。您可以使用 0 來指示查詢結果應永遠保留在快取中。當調用 yii\db\Connection::cache() 而未指定持續時間時,此屬性是使用的預設值。
  • queryCache:這表示快取應用程式組件的 ID。預設為 'cache'。僅當存在有效的快取應用程式組件時,才啟用查詢快取。

用法

如果您有多個需要利用查詢快取的 SQL 查詢,則可以使用 yii\db\Connection::cache()。用法如下:

$duration = 60;     // cache query results for 60 seconds.
$dependency = ...;  // optional dependency

$result = $db->cache(function ($db) {

    // ... perform SQL queries here ...

    return $result;

}, $duration, $dependency);

匿名函式中的任何 SQL 查詢都將以指定的依賴性快取指定的持續時間。如果在快取中找到有效的查詢結果,則將跳過查詢,並且結果將改為從快取中提供。如果您未指定 $duration 參數,則將改為使用 queryCacheDuration 的值。

有時在 cache() 中,您可能想要對某些特定查詢停用查詢快取。在這種情況下,您可以使用 yii\db\Connection::noCache()

$result = $db->cache(function ($db) {

    // SQL queries that use query caching

    $db->noCache(function ($db) {

        // SQL queries that do not use query caching

    });

    // ...

    return $result;
});

如果您只想對單個查詢使用查詢快取,則可以在建構命令時調用 yii\db\Command::cache()。例如,

// use query caching and set query cache duration to be 60 seconds
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();

您也可以使用 yii\db\Command::noCache() 來停用單個命令的查詢快取。例如,

$result = $db->cache(function ($db) {

    // SQL queries that use query caching

    // do not use query caching for this command
    $customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();

    // ...

    return $result;
});

限制

查詢快取不適用於包含資源處理程式的查詢結果。例如,當在某些 DBMS 中使用 BLOB 欄位類型時,查詢結果將傳回欄位資料的資源處理程式。

某些快取儲存具有大小限制。例如,memcache 將每個條目的最大大小限制為 1MB。因此,如果查詢結果的大小超過此限制,則快取將失敗。

快取刷新

當您需要使所有儲存的快取資料失效時,可以調用 yii\caching\Cache::flush()

您也可以通過調用 yii cache/flush 從主控台刷新快取。

  • yii cache:列出應用程式中可用的快取
  • yii cache/flush cache1 cache2:刷新快取組件 cache1cache2(您可以傳遞多個組件名稱,以空格分隔)
  • yii cache/flush-all:刷新應用程式中的所有快取組件
  • yii cache/flush-schema db:清除給定連線組件的 DB 結構描述快取

資訊: 主控台應用程式預設使用單獨的配置文件。確保您的 Web 和主控台應用程式配置中具有相同的快取組件,以達到適當的效果。

發現錯字或您認為此頁面需要改進?
在 github 上編輯它 !